import base64
import json
import random

import execjs
import requests


class YiClick:

    def __init__(self):
        self.headers = {
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "Pragma": "no-cache",
            "Referer": "https://dun.163.com/",
            "Sec-Fetch-Dest": "script",
            "Sec-Fetch-Mode": "no-cors",
            "Sec-Fetch-Site": "same-site",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
        }

        self._custom_url = "http://api.jfbym.com/api/YmServer/customApi"
        self._headers = {
            'Content-Type': 'application/json'
        }

        with open('网易点选.js', encoding='utf-8') as f:
            js_code = f.read()

        self.js = execjs.compile(js_code)
        # 点选文字坐标
        self.points = []
        # 鼠标轨迹
        self.click_track = []

    def get_bg(self):
        url = "https://c.dun.163.com/api/v3/get"
        params = {
            "referer": "https://dun.163.com/trial/picture-click",
            "zoneId": "CN31",
            "dt": "SjodO0PzucJAVlUUABPB6Gr9RD67vCy7",
            "acToken": "9ca17ae2e6ffcda170e2e6ee85f746868ba8b5c880edb08aa3d44b979b9f83c53e98eabca7c94b93988386ce2af0feaec3b92ab8f59dd8e65fa2b382a8f65b979f8fb7d54f898ee5b4f465a7bfa5b2d76783e8ee9e",
            "id": "07e2387ab53a4d6f930b8d9a9be71bdf",
            "fp": self.js.call("get_fp"),
            "https": "true",
            "type": "3",
            "version": "2.26.1",
            "dpr": "1.5",
            "dev": "1",
            "cb": self.js.call("get_cb"),
            "ipv6": "false",
            "runEnv": "10",
            "group": "",
            "scene": "",
            "lang": "zh-CN",
            "sdkVersion": "undefined",
            "iv": "3",
            "width": "320",
            "audio": "false",
            "sizeType": "10",
            "smsVersion": "v3",
            "token": "",
            "callback": self.js.call("get_callback")
        }

        response = requests.get(url, headers=self.headers, params=params)

        res = json.loads(response.text.split('(')[1].split(')')[0])
        bg_url = res['data']['bg'][0]
        front = res['data']['front']
        token = res['data']['token']
        # print(response)
        print(front, token)

        res = requests.get(bg_url, headers=self.headers)
        open('bg.jpg', 'wb').write(res.content)
        point = self.click_verify(res.content, front)
        # point = "199,113|99,108|269,92"
        # token = "e6b6273c1afd4d2daef9e979485b24f6"
        click_point_array = point.split("|")

        x = int(click_point_array[0].split(',')[0])
        y = int(click_point_array[0].split(',')[1])
        t = random.randint(20, 100)  # 初始时间 即为第二个数组的时间  后续时间累加操作就可以了
        self.click_track.append([x, y, t])
        self.points.append([x, y, t + random.randint(20, 100)])
        for index in range(1, len(click_point_array)):
            next_x = int(click_point_array[index].split(',')[0])
            next_y = int(click_point_array[index].split(',')[1])
            t = self.get_click_track(x, y, next_x, next_y, t)
            x = next_x
            y = next_y
            self.points.append([x, y, t + random.randint(20, 100)])

        print("文字点选轨迹：", self.click_track)
        print("点选轨迹长度：", len(self.click_track))
        print("点选文字坐标：", self.points)
        return token, point

    def click_verify(self, image, extra="", verify_type="300010"):
        payload = {
            "image": base64.b64encode(image).decode(),
            "extra": extra,
            "token": '7pE3vAgqNa3cDZ4iQULCogDd6oupapu9BVOLI9Fj32U',
            "type": verify_type
        }

        resp = requests.post(self._custom_url, headers=self._headers, data=json.dumps(payload))
        print(resp.text)
        return resp.json()['data']['data']

    def check(self, token, point):
        # self.click_track = [[180,65,215],[179,65,255],[178,65,775],[178,66,783],[177,66,806],[175,67,808],[175,68,815],[173,69,823],[171,71,831],[168,71,839],[165,73,847],[161,75,855],[158,77,863],[155,79,871],[149,81,879],[143,83,887],[137,86,894],[129,89,903],[121,91,911],[114,95,919],[107,97,927],[101,98,935],[95,99,943],[89,100,951],[83,100,959],[78,100,967],[72,100,975],[66,100,983],[61,101,991],[57,101,999],[54,102,1009],[51,103,1015],[49,103,1031],[46,103,1039],[45,103,1055],[44,103,1063],[43,103,1128],[43,102,1151],[44,101,1167],[45,100,1183],[45,99,1191],[46,99,1207],[46,98,1215],[47,97,1222],[48,97,1679],[49,97,1687],[50,97,1695],[52,97,1704],[55,98,1711],[58,99,1720],[61,99,1728],[67,100,1735],[75,101,1743],[83,102,1752],[93,104,1761],[105,105,1768],[114,105,1776],[126,105,1784],[137,105,1792],[148,105,1799],[159,105,1807],[170,105,1816],[179,105,1823],[186,105,1831],[195,105,1839],[204,105,1847],[213,103,1855],[221,101,1863],[227,100,1871],[233,99,1879],[238,99,1888],[243,99,1895],[247,98,1903],[249,97,1912],[251,97,1919],[252,97,1943],[253,96,1992],[254,95,2023],[255,95,2191]]
        # self.points = [[181,65,0],[47,97,1441],[255,95,2345]]
        url = "https://c.dun.163.com/api/v3/check"
        params = {
            "referer": "https://dun.163.com/trial/picture-click",
            "zoneId": "CN31",
            "dt": "SjodO0PzucJAVlUUABPB6Gr9RD67vCy7",
            "id": "07e2387ab53a4d6f930b8d9a9be71bdf",
            "token": token,
            "acToken": "undefined",
            "width": "320",
            "type": "3",
            "version": "2.26.1",
            "cb": self.js.call("get_cb"),
            "extraData": "",
            "bf": "0",
            "runEnv": "10",
            "sdkVersion": "undefined",
            "iv": "3",
            "callback": self.js.call("get_callback")
        }

        data = {
            "d": "",
            "m": self.js.call("get_m", token, self.click_track),
            "p": self.js.call("get_p", token, self.points),
            "ext": self.js.call("get_ext", token, len(self.click_track)),
        }

        params['data'] = json.dumps(data, ensure_ascii=False, separators=(",", ":"))
        print(params)
        response = requests.get(url, headers=self.headers, params=params)

        print(response.text)
        print(response)

    """ 
        鼠标轨迹模拟
            x，y 初始坐标
            next_x, next_y 下一个位置坐标
    """

    def get_click_track(self, x, y, next_x, next_y, t):

        n_x = abs(next_x - x)  # 两点坐标距离差
        n_y = abs(next_y - y)  # 两点坐标距离差
        new_x = x  # 记录移动坐标点
        new_y = y  # 记录移动坐标点

        # 用于标记y轴是否移动
        count = 0
        flag = 0
        repetition = int(n_x / 5)  # 重复x出现的个数
        while True:
            i = random.randint(0, 3)  # 随机移动距离
            gap = abs(new_x - x)
            if gap <= n_x:
                # x坐标变化
                if new_x - next_x <= 0:
                    new_x += i
                else:
                    new_x -= i
                # 边界判断
                new_x = random.randint(5, 20) if new_x < 0 else new_x
                new_x = random.randint(300, 315) if new_x > 320 else new_x

            # 时间变化
            t += random.randint(3, 10)

            # 随机y坐标重复数
            if flag > random.randint(3, 6):
                count = 0
                flag = 0
            self.click_track.append([new_x, new_y, t])
            flag += 1

            if count == 0:
                # y坐标变化
                if new_y - next_y <= 0:
                    new_y += random.randint(0, 5)
                else:
                    new_y -= random.randint(0, 5)
                # 边界判断
                new_y = random.randint(5, 20) if new_y < 0 else new_y
                new_y = random.randint(140, 155) if new_y > 160 else new_y

                # 时间变化
                t += random.randint(3, 10)

                count += 1
                self.click_track.append([new_x, new_y, t])
                flag += 1

            # x坐标重复数
            if random.randint(0, 1):
                if repetition:
                    i = random.randint(0, 3)
                    # x坐标变化
                    if new_x - next_x <= 0:
                        new_x += i
                    else:
                        new_x -= i

                    new_x = random.randint(5, 20) if new_x < 0 else new_x
                    new_x = random.randint(300, 315) if new_x > 320 else new_x

                    # 时间变化
                    t += random.randint(3, 10)

                    self.click_track.append([new_x, new_y, t])
                    flag += 1
                    repetition -= 1

            # 移动坐标和下一个坐标点相差不大退出循环
            if abs(new_x - next_x) <= 5 and abs(new_y - next_y) <= 3:
                break
        # 返回累加时间用于下一次计算
        return t


if __name__ == '__main__':
    y = YiClick()
    token, point = y.get_bg()
    y.check(token, point)
